package xyz.xuminghai.javafx_learn.scene.canvas;

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.geometry.Insets;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.scene.ImageCursor;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.ColorPicker;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.StrokeLineCap;
import javafx.scene.text.Font;
import javafx.stage.Stage;

import java.io.FileNotFoundException;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;

/**
 * 2023/6/2 17:07 星期五<br/>
 * 画布
 *
 * @author xuMingHai
 */
public class CanvasApp extends Application {

    private final ColorPicker colorPicker = new ColorPicker(Color.BLACK);

    private final Label label = new Label("画板");

    private final StackPane stackPane = new StackPane(colorPicker, label);

    private final Canvas canvas = new Canvas(600.0, 400.0);

    private final Pane canvasPane = new Pane(canvas);

    private final VBox root = new VBox(50.0, stackPane, canvasPane);


    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void init() throws Exception {
        colorPicker.setVisible(false);

        label.setFont(Font.font("华文彩云", 40.0));
        label.textFillProperty().bind(colorPicker.valueProperty());
        label.setOnMouseClicked(event -> colorPicker.show());

        String fileName = "pen.png";
        URL url = getClass().getResource(fileName);
        if (url == null) {
            throw new FileNotFoundException(fileName);
        }
        ImageCursor imageCursor = new ImageCursor(new Image(url.toExternalForm()), 0.0, 30.0);
        canvas.setCursor(imageCursor);

        // 画板操作
        GraphicsContext graphicsContext = canvas.getGraphicsContext2D();
        // paint 监听
        label.textFillProperty().addListener((observable, oldValue, newValue) -> graphicsContext.setStroke(newValue));


        // 设置线段的端点形状
        graphicsContext.setLineCap(StrokeLineCap.ROUND);
        // 操作队列
        LinkedList<List<Point2D>> linkedList = new LinkedList<>();
        LinkedList<Paint> paintLinkedList = new LinkedList<>();

        EventHandler<MouseEvent> mouseHandler = new EventHandler<>() {

            private List<Point2D> operation = null;

            @Override
            public void handle(MouseEvent event) {
                if (event.getButton() == MouseButton.PRIMARY) {
                    EventType<? extends MouseEvent> eventType = event.getEventType();
                    if (eventType == MouseEvent.MOUSE_PRESSED) {
                        operation = new LinkedList<>();
                        double x = event.getX(), y = event.getY();
                        graphicsContext.lineTo(x, y);
                        graphicsContext.stroke();
                        operation.add(new Point2D(x, y));
                    } else if (eventType == MouseEvent.MOUSE_DRAGGED) {
                        double x = event.getX(), y = event.getY();
                        graphicsContext.lineTo(x, y);
                        graphicsContext.stroke();
                        operation.add(new Point2D(x, y));
                    } else {
                        graphicsContext.beginPath();
                        linkedList.add(operation);
                        paintLinkedList.add(graphicsContext.getStroke());
                        operation = null;
                    }
                }
            }
        };

        canvas.setOnMousePressed(mouseHandler);
        canvas.setOnMouseDragged(mouseHandler);
        canvas.setOnMouseReleased(mouseHandler);

        canvas.setOnMouseClicked(event -> {
            MouseButton mouseButton = event.getButton();
            if (mouseButton == MouseButton.SECONDARY) {
                if (linkedList.pollLast() != null) {
                    // 删除路径颜色
                    paintLinkedList.removeLast();
                    // 清空画布
                    graphicsContext.clearRect(0.0, 0.0, canvas.getWidth(), canvas.getHeight());
                    // 保存当前颜色
                    Paint currentPaint = graphicsContext.getStroke();
                    // 重新绘制之前的操作
                    for (int i = 0; i < linkedList.size(); i++) {
                        List<Point2D> list = linkedList.get(i);
                        Paint paint = paintLinkedList.get(i);
                        graphicsContext.setStroke(paint);
                        list.forEach(point2D -> {
                            graphicsContext.lineTo(point2D.getX(), point2D.getY());
                            graphicsContext.stroke();
                        });
                        graphicsContext.beginPath();
                    }
                    // 恢复颜色
                    graphicsContext.setStroke(currentPaint);
                }
            } else if (mouseButton == MouseButton.MIDDLE) {
                // 清空画布
                graphicsContext.clearRect(0.0, 0.0, canvas.getWidth(), canvas.getHeight());
                // 清空操作
                linkedList.clear();
                paintLinkedList.clear();
            }
        });

        // 设置画板边框、背景
        canvasPane.setBorder(new Border(new BorderStroke(null, BorderStrokeStyle.DASHED, null, null, new Insets(-1.0))));
        canvasPane.setBackground(new Background(new BackgroundFill(Color.WHITE, null, null)));


        root.setAlignment(Pos.CENTER);
        root.setFillWidth(false);

    }

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle(getClass().getSimpleName());
        Scene scene = new Scene(root, 800, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

}
